package com.tanhua.manager.service;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tanhua.manager.domain.Log;
import com.tanhua.manager.mapper.AnalysisMapper;
import com.tanhua.manager.mapper.LogMapper;
import com.tanhua.manager.utils.ComputeUtil;
import com.tanhua.manager.vo.AnalysisByDay;
import com.tanhua.manager.vo.AnalysisChartDataItem;
import com.tanhua.manager.vo.AnalysisChartDataVO;
import com.tanhua.manager.vo.AnalysisSummaryVO;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author 阿鹏
 * @date 2021/2/21 14:37
 */
@Service
public class AnalysisService extends ServiceImpl<AnalysisMapper, AnalysisByDay> {

    @Autowired
    private AnalysisMapper analysisMapper;
    @Autowired
    private LogMapper logMapper;

    public ResponseEntity summary() {
        AnalysisSummaryVO vo = new AnalysisSummaryVO();

        // cumulativeUsers 累计用户数
        Long cumulativeUsers = this.analysisMapper.cumulativeUsers();
        vo.setCumulativeUsers(cumulativeUsers);

        // activePassMonth 过去30天活跃用户数
        Date now = new Date();
        String today = DateUtil.date(now).toString("yyyy-MM-dd");
        String date30 = DateUtil.offsetDay(now, -30).toString("yyyy-MM-dd");
        Long activePassMonth = this.analysisMapper.queryCountByBetweenAnd(date30, today);
        vo.setActivePassMonth(activePassMonth.longValue());

        // activePassWeek 过去7天活跃用户
        String date7 = DateUtil.offsetDay(now, -7).toString("yyyy-MM-dd");
        Long activePassWeek = this.analysisMapper.queryCountByBetweenAnd(date7, today);
        vo.setActivePassWeek(activePassWeek.longValue());

        // newUsersToday 今日新增用户数量
        QueryWrapper<AnalysisByDay> wrapper = new QueryWrapper<>();
        wrapper.eq("record_date", today);
        AnalysisByDay analysisByDayToday = this.analysisMapper.selectOne(wrapper);
        Integer newUsersToday = analysisByDayToday.getNumRegistered();
        vo.setNewUsersToday(newUsersToday.longValue());

        // newUsersTodayRate 今日新增用户涨跌率
        String yesterday = DateUtil.offsetDay(now, -1).toString("yyyy-MM-dd");
        wrapper = new QueryWrapper<>();
        wrapper.eq("record_date", yesterday);
        AnalysisByDay analysisByDayYesterday = this.analysisMapper.selectOne(wrapper);
        Integer numRegisteredYesterday = analysisByDayYesterday.getNumRegistered();
        BigDecimal newUsersTodayRate = ComputeUtil.computeRate(newUsersToday.longValue(), numRegisteredYesterday.longValue());
        vo.setNewUsersTodayRate(newUsersTodayRate);

        // loginTimesToday 今日登录次数
        Integer loginTimesToday = analysisByDayToday.getNumLogin();
        vo.setLoginTimesToday(loginTimesToday.longValue());

        // loginTimesTodayRate 今日登录次数涨跌率
        Integer loginTimesYesterday = analysisByDayYesterday.getNumLogin();
        BigDecimal loginTimesTodayRate = ComputeUtil.computeRate(loginTimesToday.longValue(), loginTimesYesterday.longValue());
        vo.setLoginTimesTodayRate(loginTimesTodayRate);

        // activeUsersToday 今日活跃用户数量
        Integer activeUsersToday = analysisByDayToday.getNumActive();
        vo.setActiveUsersToday(activeUsersToday.longValue());

        // activeUsersTodayRate 今日活跃用户涨跌率
        Integer activeUsersYesterday = analysisByDayYesterday.getNumActive();
        BigDecimal activeUsersTodayRate = ComputeUtil.computeRate(activeUsersToday.longValue(), activeUsersYesterday.longValue());
        vo.setActiveUsersTodayRate(activeUsersTodayRate);

        return ResponseEntity.ok(vo);
    }

    public ResponseEntity usersChartData(Long sd, Long ed, Integer type) {
        String column = getColumn(type);

        AnalysisChartDataVO vo = new AnalysisChartDataVO();

        String startTime = DateUtil.date(sd).toDateStr();
        String endTime = DateUtil.date(ed).toDateStr();
        List<AnalysisByDay> thisYear =
                query().between("record_date", startTime, endTime).select("record_date, " + column)
                        .list();
        List<AnalysisChartDataItem> thisYearItemList = data2Vo(thisYear, type);
        vo.setThisYear(thisYearItemList);

        startTime = DateUtil.date(sd).offset(DateField.YEAR, -1).toDateStr();
        endTime = DateUtil.date(ed).offset(DateField.YEAR, -1).toDateStr();
        List<AnalysisByDay> lastYear =
                query().between("record_date", startTime, endTime).select("record_date, " + column)
                        .list();
        List<AnalysisChartDataItem> lastYearItemList = data2Vo(lastYear, type);
        vo.setLastYear(lastYearItemList);

        return ResponseEntity.ok(vo);
    }

    private List<AnalysisChartDataItem> data2Vo(List<AnalysisByDay> thisYear, Integer type) {
        List<AnalysisChartDataItem> itemList = new ArrayList<>();

        for (AnalysisByDay analysis : thisYear) {
            AnalysisChartDataItem item = new AnalysisChartDataItem();

            item.setTitle(new DateTime(analysis.getRecordDate()).toString("yyyy-MM-dd"));
            //101 新增 102 活跃用户 103 次日留存率
            if (type == 101) {
                item.setAmount(analysis.getNumRegistered().longValue());
            } else if (type == 102) {
                item.setAmount(analysis.getNumActive().longValue());
            } else if (type == 103) {
                item.setAmount(analysis.getNumRetention1d().longValue());
            }
            itemList.add(item);
        }

        return itemList;
    }

    private String getColumn(Integer type) {
        //101 新增 102 活跃用户 103 次日留存率
        if (type == 101) {
            return "num_registered";
        } else if (type == 102) {
            return "num_active";
        } else if (type == 103) {
            return "num_retention1d";
        }
        return null;
    }

    public void analysis() {
        // 准备统计日期
        Date now = new Date();
        String today = DateUtil.format(now, "yyyy-MM-dd");
        String yesterday = DateUtil.offsetDay(now, -1).toString("yyyy-MM-dd");

        // 如果统计记录结果不存在,就新增一条
        AnalysisByDay analysis = query().eq("record_date", today).one();
        if (analysis == null) {
            analysis = new AnalysisByDay();
            analysis.setRecordDate(now);
            analysis.setCreated(now);
            analysis.setUpdated(now);

            save(analysis);
        }

        //3. 统计数据
        //3.1 今日新增用户数
        QueryWrapper<Log> wrapper = new QueryWrapper<>();
        wrapper.eq("TYPE", "0102");
        wrapper.eq("log_time", today);
        Integer register = logMapper.selectCount(wrapper);
        analysis.setNumRegistered(register);

        //3.2 今日登录次数
        wrapper = new QueryWrapper<>();
        wrapper.eq("TYPE", "0101");
        wrapper.eq("log_time", today);
        Integer login = logMapper.selectCount(wrapper);
        analysis.setNumLogin(login);

        //3.3 今日活跃用户数
        wrapper = new QueryWrapper<>();
        wrapper.eq("log_time", today);
        wrapper.select("distinct user_id");
        Integer active = logMapper.selectCount(wrapper);
        analysis.setNumActive(active);

        // 3.4 留存
        int retentionCount = logMapper.queryRetentionCount(today, yesterday);
        analysis.setNumRetention1d(retentionCount);

        updateById(analysis);
    }
}
